package ibm.cognos.imt; /**
 * ExecuteReportSpec.java
 *
 * Licensed Material - Property of IBM
 * © Copyright IBM Corp. 2003, 2010
 *
 * Description: Technote 1344378 - SDK Sample to execute a report using the report specification
 *
 * Tested with: IBM Cognos BI 10.1, Java 5.0 
 */

import com.cognos.developer.schemas.bibus._3.*;
import org.apache.axis.client.Stub;
import org.apache.axis.encoding.Base64;
import org.apache.axis.message.SOAPHeaderElement;

import javax.xml.namespace.QName;
import java.io.File;
import java.io.FileOutputStream;

public class ExecuteReportSpec {
	private ContentManagerService_PortType cmService = null;
	private ReportService_PortType reportService = null;

	public ExecuteReportSpec(String sendPoint) {
		ContentManagerService_ServiceLocator cmServiceLocator = new ContentManagerService_ServiceLocator();
		ReportService_ServiceLocator rsServiceLocator = new ReportService_ServiceLocator();

		try {
			// create the binding objects
			cmService = cmServiceLocator
					.getcontentManagerService(new java.net.URL(sendPoint));
			reportService = rsServiceLocator.getreportService(new java.net.URL(
					sendPoint));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public String logon(String namespace, String uid, String pwd) {
		StringBuffer credentialXML = new StringBuffer();

		credentialXML.append("<credential>");
		credentialXML.append("<namespace>").append(namespace).append(
				"</namespace>");
		credentialXML.append("<username>").append(uid).append("</username>");
		credentialXML.append("<password>").append(pwd).append("</password>");
		credentialXML.append("</credential>");

		String encodedCredentials = credentialXML.toString();
		XmlEncodedXML xmlCredentials = new XmlEncodedXML();
		xmlCredentials.set_value(encodedCredentials);

		try {
			System.out.println("Logging on");
			cmService.logon(xmlCredentials, null);

			SOAPHeaderElement temp = ((Stub) cmService).getResponseHeader(
					"http://developer.cognos.com/schemas/bibus/3/",
					"biBusHeader");
			BiBusHeader cmBiBusHeader = (BiBusHeader) temp
					.getValueAsType(new QName(
							"http://developer.cognos.com/schemas/bibus/3/",
							"biBusHeader"));
			((Stub) cmService).setHeader(
					"http://developer.cognos.com/schemas/bibus/3/",
					"biBusHeader", cmBiBusHeader);

		} catch (Exception e) {
			System.out.println(e);
		}
		return ("Logon successful as " + uid);
	}

	public void executeReport(String reportName, String format, String savePath) {
		String textOutput = null;
		byte binaryOutput[] = null;

		Option[] runOptions = new Option[3];

		RunOptionBoolean rob = new RunOptionBoolean();
		RunOptionStringArray rosa = new RunOptionStringArray();
		RunOptionBoolean rop = new RunOptionBoolean();

		// We do not want to save this output
		rob.setName(RunOptionEnum.saveOutput);
		rob.setValue(false);

		// What format do we want the report in: PDF, HTML, or XML?
		rosa.setName(RunOptionEnum.outputFormat);
		rosa.setValue(new String[] { format });

		// Set the report not to prompt as we pass the parameter if any
		rop.setName(RunOptionEnum.prompt);
		rop.setValue(false);

		// Fill the array with the run options.
		runOptions[0] = rob;
		runOptions[1] = rosa;
		runOptions[2] = rop;

		SearchPathMultipleObject spMulti = new SearchPathMultipleObject();
		spMulti.set_value(reportName);

		try {

			// query for the specification of the report.
			PropEnum[] confprop = { PropEnum.searchPath, PropEnum.specification };
			System.out.println("Query for the report specification");
			BaseClass[] bc = cmService.query(spMulti, confprop, new Sort[] {},
					new QueryOptions());

			if (bc != null && bc.length > 0) {
				// at this point the specification could be modified using
				// string
				// manipulation or DOM.
				String strSpec = ((Report) bc[0]).getSpecification().getValue();

				ReportServiceReportSpecification rs = new ReportServiceReportSpecification();
				Specification spec = new Specification();
				spec.set_value(strSpec);
				rs.setValue(spec);
				System.out
						.println("Execute the report using the xml specification");
				// call the execute method passing a specification and not a
				// search path.
				AsynchReply rsr = getReportService().runSpecification(rs,
						new ParameterValue[] {}, runOptions);

				if (rsr.getStatus() != AsynchReplyStatusEnum.complete) {
					while (rsr.getStatus() != AsynchReplyStatusEnum.complete
							&& rsr.getStatus() != AsynchReplyStatusEnum.conversationComplete) {
						if (hasSecondaryRequest(rsr, "wait")) {
							System.out
									.println("Waiting... execute is not complete");
							rsr = getReportService().wait(
									rsr.getPrimaryRequest(),
									new ParameterValue[] {}, new Option[] {});
						} else {
							System.out
									.println("Error: Wait method not available as expected.");
						}

					}
					if (hasSecondaryRequest(rsr, "getOutput")) {
						rsr = getReportService().getOutput(
								rsr.getPrimaryRequest(),
								new ParameterValue[] {}, new Option[] {});
					} else {
						System.out
								.println("Error: getOutput method not available as expected.");
					}
				}
				if (rsr != null)
					for (int i = 0; i < rsr.getDetails().length; i++) {
						if (rsr.getDetails()[i] instanceof AsynchDetailReportOutput)
							textOutput = ((AsynchDetailReportOutput) rsr
									.getDetails()[i]).getOutputPages()[0];

					}

				File oFile = new File(savePath + "." + format);
				FileOutputStream fos = new FileOutputStream(oFile);
				System.out
						.println("Execute complete saving to the file system");
				if (format.equals("PDF") || format.equals("CSV")) {
					binaryOutput = Base64.decode(textOutput); // decode the
					// PDF/CSV
					// output to
					// array of
					// bytes.
					if (binaryOutput != null)
						fos.write(binaryOutput);
				} else {
					if (textOutput != null)
						fos.write(textOutput.getBytes());
				}
				fos.flush();
				fos.close();
				System.out.println("Report execution complete. File saved to "
						+ savePath + "." + format);
			} else {
				System.out.println("Error: Report not found");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public ReportService_PortType getReportService(boolean isNewConversation,
			String RSGroup) {

//		BiBusHeader bibus = null;
//		bibus = getHeaderObject(((Stub) reportService).getResponseHeader(
//				"http://developer.cognos.com/schemas/bibus/3/", "biBusHeader"),
//				isNewConversation, RSGroup);
//
//		if (bibus == null) {
//			BiBusHeader CMbibus = null;
//			CMbibus = getHeaderObject(((Stub) cmService).getResponseHeader(
//					"http://developer.cognos.com/schemas/bibus/3/",
//					"biBusHeader"), true, RSGroup);
//
//			((Stub) reportService).setHeader(
//					"http://developer.cognos.com/schemas/bibus/3/",
//					"biBusHeader", CMbibus);
//		} else {
//			((Stub) reportService).clearHeaders();
//			((Stub) reportService).setHeader(
//					"http://developer.cognos.com/schemas/bibus/3/",
//					"biBusHeader", bibus);
//
//		}

		return reportService;
	}

	// handle report service requests that do not specify new conversation for
	// backwards compatibility
	public ReportService_PortType getReportService() {

		return getReportService(false, "");

	}

	// Use this method when copying headers, such as for requests to services
	public static BiBusHeader getHeaderObject(SOAPHeaderElement SourceHeader,
			boolean isNewConversation, String RSGroup) {
		if (SourceHeader == null)
			return null;

		BiBusHeader bibus = null;
		try {
			bibus = (BiBusHeader) SourceHeader.getValueAsType(new QName(
					"http://developer.cognos.com/schemas/bibus/3/",
					"biBusHeader"));

			// If the header will be used for a new conversation, clear
			// tracking information, and set routing if supplied (clear if not)
			if (isNewConversation) {

				bibus.setTracking(null);

				// If a Routing Server Group is specified, direct requests to it
				if (RSGroup.length() > 0) {
					RoutingInfo routing = new RoutingInfo(RSGroup);
					bibus.setRouting(routing);
				} else {
					bibus.setRouting(null);
				}
			}
		} catch (Exception e) {

			e.printStackTrace();
		}

		return bibus;
	}

	public boolean hasSecondaryRequest(AsynchReply response,
			String secondaryRequest) {
		AsynchSecondaryRequest[] secondaryRequests = response
				.getSecondaryRequests();
		for (int i = 0; i < secondaryRequests.length; i++) {
			if (secondaryRequests[i].getName().compareTo(secondaryRequest) == 0) {
				return true;
			}
		}
		return false;
	}

	public static void main(String[] args) {
		// searchPath used to query for the report specification.
		String reportPath = "/content/folder[@name='Samples']/folder[@name='Models']/package[@name='GO Sales (query)']/folder[@name='Report Studio Report Samples']/report[@name='Horizontal Pagination']";
		// change format to (PDF, CSV, HTML, HTMLFragment, XML, XLWA) NOTE: XLS
		// requires additional work please see knowledge base sample
		// execute a report as XLS
		String format = "XML";
		// report endpoint URL
		String reportNetEndPoint = "http://9.119.141.187:9300/p2pd/servlet/dispatch";
		// file location and FILE name
		String savePath = "c:\\temp\\reportOutput";
		ExecuteReportSpec emf = new ExecuteReportSpec(reportNetEndPoint);
//		emf.logon("nameSpaceID", "userName", "password");
		emf.executeReport(reportPath, format, savePath);
	}
}
